package com.hyt.it.ogt.kq.service.bm.service.impl;


import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.util.encoders.Base64;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.hyt.core.base.BaseServiceImpl;
import com.hyt.core.util.FastJsonUtil;
import com.hyt.core.util.UUIDUtils;
import com.hyt.it.ogt.cj.enums.ComponentNameEnum;
import com.hyt.it.ogt.cj.service.IProjectCollectInfoService;
import com.hyt.it.ogt.kq.common.bm.enums.BmInvoiceStatusEnum;
import com.hyt.it.ogt.kq.common.bm.enums.OrderInvioiceStatusEnum;
import com.hyt.it.ogt.kq.service.bm.den.ExcelExport;
import com.hyt.it.ogt.kq.service.bm.feign.tps.TpsClient;
import com.hyt.it.ogt.kq.service.bm.mapper.InvoiceMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.InvoiceResultMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.OrderMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.ProjectMapper;
import com.hyt.it.ogt.kq.service.bm.mapper.StudentSubjectMidOrderDetailsMapper;
import com.hyt.it.ogt.kq.service.bm.model.entity.Invoice;
import com.hyt.it.ogt.kq.service.bm.model.entity.InvoiceAddr;
import com.hyt.it.ogt.kq.service.bm.model.entity.InvoiceEnterprise;
import com.hyt.it.ogt.kq.service.bm.model.entity.InvoiceItem;
import com.hyt.it.ogt.kq.service.bm.model.entity.InvoiceMidOrder;
import com.hyt.it.ogt.kq.service.bm.model.entity.InvoiceResult;
import com.hyt.it.ogt.kq.service.bm.model.entity.Order;
import com.hyt.it.ogt.kq.service.bm.model.entity.Project;
import com.hyt.it.ogt.kq.service.bm.model.vo.CallBackParam;
import com.hyt.it.ogt.kq.service.bm.model.vo.InvoiceApply;
import com.hyt.it.ogt.kq.service.bm.model.vo.InvoiceApplyParam;
import com.hyt.it.ogt.kq.service.bm.model.vo.InvoiceApplyVo;
import com.hyt.it.ogt.kq.service.bm.model.vo.InvoiceNotifyEvent;
import com.hyt.it.ogt.kq.service.bm.model.vo.InvoiceNotifyVo;
import com.hyt.it.ogt.kq.service.bm.model.vo.InvoiceParam;
import com.hyt.it.ogt.kq.service.bm.model.vo.InvoiceSaveVo;
import com.hyt.it.ogt.kq.service.bm.model.vo.InvoiceVo;
import com.hyt.it.ogt.kq.service.bm.service.IInvoiceAddrService;
import com.hyt.it.ogt.kq.service.bm.service.IInvoiceEnterpriseService;
import com.hyt.it.ogt.kq.service.bm.service.IInvoiceItemService;
import com.hyt.it.ogt.kq.service.bm.service.IInvoiceMidOrderService;
import com.hyt.it.ogt.kq.service.bm.service.IInvoiceResultService;
import com.hyt.it.ogt.kq.service.bm.service.IInvoiceService;
import com.hyt.loginfo.model.User;
import com.hyt.loginfo.util.UserIdToNameUtil;
import com.hyt.model.PageParam;
import com.hyt.model.tps.entity.InvoiceBase;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * <p>
 * 发票详细信息表 服务实现类
 * </p>
 *
 * @author liteng
 * @since 2020-08-28
 */
@Service
@Slf4j
public class InvoiceServiceImpl extends BaseServiceImpl<InvoiceMapper, Invoice> implements IInvoiceService {

    @Autowired
    private InvoiceMapper invoiceMapper;
    @Autowired
    private OrderMapper iOrderMapper;
    @Autowired
    private ProjectMapper projectMapper;
    @Autowired
    private StudentSubjectMidOrderDetailsMapper studentSubjectMidOrderDetailsMapper;
    @Autowired
    private IInvoiceAddrService iInvoiceAddrService;
    @Autowired
    private IInvoiceItemService iInvoiceItemService;
    @Autowired
    private IInvoiceEnterpriseService iInvoiceEnterpriseService;
    @Autowired
    private IInvoiceMidOrderService iInvoiceMidOrderService;
    @Autowired
    private IInvoiceResultService invoiceResultService;
    @Autowired
    private InvoiceResultMapper invoiceResultMapper;
    @Autowired
    private TpsClient tpsClient;
    @Resource
    UserIdToNameUtil<InvoiceVo> userIdToNameUtil;
    @Resource
    IProjectCollectInfoService iProjectCollectInfoService;

    @Override
    public IPage<InvoiceVo> queryInvoiceProject(PageParam<InvoiceVo> pageParam, InvoiceParam param) {
        return invoiceMapper.queryInvoiceProject(pageParam, param);
    }

    @Override
    public IPage<InvoiceVo> queryInvoice(InvoiceParam param) {
        // 如果没有机构采集信息则不设置机构权限查询
        Boolean hasOfficePermission = iProjectCollectInfoService.isComponentRequired(param.getProjectId(), ComponentNameEnum.office.getCode());
        if (!hasOfficePermission) {
            param.setDeptIds(null);
        }
        
        IPage<InvoiceVo> page = invoiceMapper.queryInvoice(param);
        if (page.getRecords() != null && page.getRecords().size() > 0) {
            for (int i = 0; i < page.getRecords().size(); i++) {
                if (page.getRecords().get(i).getStudentNum() == 1) {
                    page.getRecords().get(i).setBussType("1");
                    if (StringUtils.isNotBlank(page.getRecords().get(i).getStudentName())) {
                        page.getRecords().get(i).setStudentName(page.getRecords().get(i).getStudentName().split(",")[0]);
                    }
                } else {
                    page.getRecords().get(i).setBussType("2");
                    page.getRecords().get(i).setStudentName("团体");
                }
            }
            userIdToNameUtil.change(page.getRecords(), InvoiceVo::getRequestUser, InvoiceVo::setRequestUser);
        }
        return page;
    }

    @Override
    public void export(InvoiceParam param, HttpServletResponse response) {
        String titleString = "studentName,buss_type,fplxdm,gmf_mc,gmf_nsrsbh," +
                "jshj,request_time,rs_code,rs_msg";
        String titleNameString = "姓名,开票类型,发票类型,发票抬头,税号,发票金额,提交时间,开票状态,备注";
        String fileName = "发票列表";
        int[] array = new int[titleString.split(",").length];
        for (int i = 0; i < array.length; i++) {
            array[i] = 20;
        }
        List<Map<String, Object>> list = invoiceMapper.queryInvoiceMap(param);
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> map = list.get(i);
            if (list.get(i).get("studentNum") != null && Integer.valueOf(list.get(i).get("studentNum").toString()) == 1) {
                if (list.get(i).get("studentName") != null && StringUtils.isNotBlank(list.get(i).get("studentName").toString())) {
                    map.put("buss_type", "个人");
                    map.put("studentName", list.get(i).get("studentName").toString().split(",")[0]);
                }
            } else {
                map.put("buss_type", "团体");
                map.put("studentName", "团体");
            }
            if ("026".equals(list.get(i).get("fplxdm").toString())) {
                list.get(i).put("fplxdm", "电子发票");
            } else {
                list.get(i).put("fplxdm", "普通纸质发票");
            }
            Date date = (Date) list.get(i).get("request_time");
            if (StringUtils.isNotBlank(list.get(i).get("request_time").toString())) {
                list.get(i).put("request_time", new SimpleDateFormat(
                        "yyyy-MM-dd HH:mm:ss").format(date));
            } else {
                list.get(i).put("request_time", "");
            }
            if ("0".equals(list.get(i).get("rs_code").toString())) {
                list.get(i).put("rs_code", "待开具");
            } else if ("1".equals(list.get(i).get("rs_code").toString())) {
                list.get(i).put("rs_code", "已发出");
            } else if ("2".equals(list.get(i).get("rs_code").toString())) {
                list.get(i).put("rs_code", "已开具");
            } else if ("3".equals(list.get(i).get("rs_code").toString())) {
                list.get(i).put("rs_code", "开具失败");
            } else if ("4".equals(list.get(i).get("rs_code").toString())) {
                list.get(i).put("rs_code", "已失效");
            }
        }
        ExcelExport excelExport = new ExcelExport();
        excelExport.exportMapExcel(response, fileName, titleString.split(","), titleNameString.split(","), array, list);
    }


    public IPage<InvoiceApplyVo> queryApplyPage(PageParam<InvoiceApplyVo> pageParam, InvoiceApplyParam param) {
        QueryWrapper<InvoiceEnterprise> enterpriseWrapper = new QueryWrapper<InvoiceEnterprise>();
        enterpriseWrapper.eq("office_id", param.getOfficeId());
        enterpriseWrapper.eq("invoice_type", param.getInvoiceType());
        InvoiceEnterprise enterprise = iInvoiceEnterpriseService.getOne(enterpriseWrapper);

        if (StringUtils.isNotBlank(param.getStudentIds())) {
            String sql = " and (";
            for (int i = 0; i < param.getStudentIds().split(",").length; i++) {
                if (i != param.getStudentIds().split(",").length - 1) {
                    sql += "m.studentId like '%" + param.getStudentIds().split(",")[i] + "%' or ";
                } else {
                    sql += "m.studentId like '%" + param.getStudentIds().split(",")[i] + "%'  ";
                }
            }
            sql += ")";
            param.setSql(sql);
        }
        IPage<InvoiceApplyVo> page = invoiceMapper.queryApplyPage(pageParam, param);
        List<InvoiceApplyVo> list = page.getRecords();
        if (enterprise != null) {
            for (int i = 0; i < list.size(); i++) {
                list.get(i).setInvoiceContent(enterprise.getContent());
            }
        }
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String saveInvoiceApply(InvoiceApply invoiceApply) throws Exception {
        try {
            // 查询发票配置信息
            InvoiceBase obj = tpsClient.queryInvoiceBase(invoiceApply.getOfficeId());

            List<Invoice> invoiceList = invoiceMapper.queryMidInvoice(invoiceApply.getOrderIds());
            if (CollUtil.isNotEmpty(invoiceList)) {
                for (int i = 0; i < invoiceList.size(); i++) {
                    invoiceList.get(i).setDelFlag(false);
                }
                this.saveOrUpdateBatch(invoiceList);
            }

            // 发票信息
            Invoice invoice = new Invoice();
            // 发票-项目明细
            InvoiceItem item = new InvoiceItem();
            // 1.邮件数据
            InvoiceAddr addr = new InvoiceAddr();
            // 邮寄地址
            addr.setEmail(invoiceApply.getGmfDzyx());
            // 开票方电话号码
            addr.setPhone(invoiceApply.getGmfSjh());
            // 接收方联系人
            addr.setAddressee(invoiceApply.getAddressee());
            // 联系地址
            addr.setAddrDetail(invoiceApply.getAddrDetail());
            // 接收类型
            addr.setReceviceType(invoiceApply.getReceviceType());
            // 
            addr.setAddrCity(invoiceApply.getAddrCity());
            addr.setAddrCounty(invoiceApply.getAddrCounty());
            addr.setAddrProv(invoiceApply.getAddrProv());

            String xmmcDefault = "";
            if (invoiceApply.getInvoiceType().equals("1")) {
                xmmcDefault = "云考试报名费";
            }
            if (invoiceApply.getInvoiceType().equals("2")) {
                xmmcDefault = "教材购买费";
            }
            Date date = new Date();
            Double sl = Double.valueOf(obj.getTaxRate());
            invoice.setAppId(obj.getAppId());
            invoice.setOfficeId(obj.getOfficeId());
            invoice.setProjectId(invoiceApply.getProjectId());
            invoice.setRequestCode(obj.getRequestCode());
            invoice.setResponseCode(obj.getResponseCode());
            invoice.setSkpNo(obj.getTaxNum());
            invoice.setSkpLx(obj.getTaxType());
            invoice.setZsfs(obj.getZsfs());
            invoice.setCallbackUrl(obj.getCallbackUrl());
            invoice.setCallbackVersion(obj.getCallbackVersion());
            invoice.setXsfNsrsbh(obj.getSellerId());
            invoice.setXsfMc(obj.getSellerName());
            invoice.setXsfDzdh(obj.getSellerAddrPhone());
            invoice.setXsfYhzh(obj.getSellerBank());
            invoice.setGmfDzyx(invoiceApply.getGmfDzyx());
            invoice.setGmfSjh(invoiceApply.getGmfSjh());
            invoice.setGmfMc(invoiceApply.getGmfMc());
            invoice.setBank(invoiceApply.getBank());
            invoice.setGmfNsrsbh(invoiceApply.getGmfNrsbh());
            invoice.setRegPhone(invoiceApply.getRegPhone());
            invoice.setGmfDzdh(invoiceApply.getGmfDzdh());
            invoice.setGmfYhzh(invoiceApply.getGmfYhzh());
            invoice.setJshj(invoiceApply.getJshj());
            invoice.setBz(invoiceApply.getBz());
            invoice.setOfficeId(invoiceApply.getOfficeId());
            invoice.setCreateBy(invoiceApply.getCreateBy());


            // 0-蓝字发票；1-红字发票
            invoice.setKplx("0");
            invoice.setKpr("会计");
            invoice.setSkr("管理员");
            invoice.setFhr("会计");
            BigDecimal divide = invoiceApply.getJshj().divide(BigDecimal.valueOf(1 + sl), 2, BigDecimal.ROUND_HALF_UP);
            invoice.setHjje(divide);
            invoice.setHjse(invoice.getHjje().multiply(BigDecimal.valueOf(sl)).setScale(2, BigDecimal.ROUND_HALF_UP));
            invoice.setTspz("00");
            invoice.setInterfaceCode("DFXJ1001");

            // 026 电子发票 007 增值税普票 004 增值税专票(专票电子化国家暂时不支持)
            invoice.setFplxdm(StringUtils.isEmpty(invoiceApply.getFplxdm()) ? "026" : invoiceApply.getFplxdm());
            invoice.setRequestTime(LocalDateTime.now());

            item.setSpbm(obj.getProductNum());
            //0 正常行、1 折扣 2 被折扣行
            item.setFphxz("0");
            item.setPayType(invoiceApply.getInvoiceType());
            item.setYhzcbs("0");
            item.setXmmc(xmmcDefault);
            item.setGgxh("***");
            item.setDw("人");
            item.setXmsl(BigDecimal.valueOf(invoiceApply.getOrderIds().split(",").length));
            item.setXmje(invoiceApply.getJshj().divide(BigDecimal.valueOf(1 + sl), 2, BigDecimal.ROUND_HALF_UP));
            item.setXmdj(invoice.getHjje().divide(BigDecimal.valueOf(invoiceApply.getOrderIds().split(",").length), 3, BigDecimal.ROUND_HALF_UP));
            item.setSl(BigDecimal.valueOf(sl));
            item.setSe(item.getXmje().multiply(item.getSl()).setScale(2, BigDecimal.ROUND_HALF_UP));
            // 流水号
            int hashCodeV = UUIDUtils.newSortUUID().toString().hashCode();
            if (hashCodeV < 0) {
                hashCodeV = -hashCodeV;
            }
            SimpleDateFormat sdformat = new SimpleDateFormat("HHmmssSSS");
            String fpqqlsh = ("HYT" + sdformat.format(date) + String.format("%09d", hashCodeV)).substring(0, 16);
            invoice.setFpqqlsh(fpqqlsh);
            // invoice.setFpqqlsh("HYT10004966518053999");
            invoice.setTaxType(invoiceApply.getTaxType());
            invoice.setBussType("1");
            invoice.setBussResult("0");
            List<String> list = new ArrayList<String>();
            if (StringUtils.isNotBlank(invoiceApply.getStudentIds())) {
                for (int i = 0; i < invoiceApply.getStudentIds().split(",").length; i++) {
                    if (i == 0) {
                        list.add(invoiceApply.getStudentIds().split(",")[0]);
                    } else {
                        boolean flag = false;
                        for (int j = 0; j < list.size(); j++) {
                            if (list.get(j).equals(invoiceApply.getStudentIds().split(",")[i])) {
                                flag = true;
                                break;
                            }
                        }
                        if (!flag) {
                            list.add(invoiceApply.getStudentIds().split(",")[i]);
                        }
                    }
                }
            }
            if (list.size() > 1) {
                invoice.setBussType("2");
            }

            // 1. 发票信息
            invoice.setRsCode("0");
            invoice.setRsMsg("待确认");
            this.save(invoice);
            item.setBmInvoiceId(invoice.getId());
            addr.setBmInvoiceId(invoice.getId());
            iInvoiceAddrService.save(addr);
            iInvoiceItemService.save(item);
            List<InvoiceMidOrder> invoiceMidOrders = new ArrayList<>();
            for (String orderDetalsId : invoiceApply.getOrderIds().split(",")) {
                if (StringUtils.isEmpty(orderDetalsId)) {
                    continue;
                }
                InvoiceMidOrder invoiceMidOrder = new InvoiceMidOrder();
                invoiceMidOrder.setBmInvoiceId(invoice.getId());
                invoiceMidOrder.setBmOrderDetailsId(orderDetalsId);
                invoiceMidOrder.setCreateBy(invoiceApply.getCreateBy());
                invoiceMidOrder.setUpdateBy(invoiceApply.getCreateBy());
                invoiceMidOrders.add(invoiceMidOrder);
                // 将订单的状态设置为申请中
                Order order = iOrderMapper.selectById(orderDetalsId);
                if (null != order) {
                    order.setInvoiceStatus(OrderInvioiceStatusEnum.RUNNING.getStatus());
                    iOrderMapper.updateById(order);
                }
            }
            StringBuilder stringBuilder = new StringBuilder();
            for (String orderDetalsId : invoiceApply.getOrderIds().split(",")) {
                if (StringUtils.isEmpty(orderDetalsId)) {
                    continue;
                }
                // 将订单的状态设置为申请中
                Order order = iOrderMapper.selectById(orderDetalsId);
                if (null != order) {
                    String projectNameAndSubjectName = getProjectNameAndSubjectName(order);
                    if (StringUtils.isNotEmpty(projectNameAndSubjectName)) {
                        stringBuilder.append(projectNameAndSubjectName);
                        stringBuilder.append(";");
                    }
                }
            }
            if (StringUtils.isNotEmpty(stringBuilder)) {
                stringBuilder = stringBuilder.deleteCharAt(stringBuilder.length() - 1);
            }
            item.setXmmc(stringBuilder.toString());
            iInvoiceItemService.saveOrUpdate(item);


            if (CollUtil.isNotEmpty(invoiceMidOrders)) {
                iInvoiceMidOrderService.saveBatch(invoiceMidOrders);
            }
            InvoiceResult invoiceResult = new InvoiceResult();
            invoiceResult.setBmInvoiceId(invoice.getId());
            invoiceResult.setRsCode("0");
            invoiceResult.setRsMsg("待确认");
            invoiceResult.setFpqqlsh(invoice.getFpqqlsh());
            invoiceResult.setKprq(LocalDateTime.now());
            invoiceResultService.save(invoiceResult);

            // 将订单的开票状态设置为申请中

            return invoice.getId();
        } catch (Exception ex) {
            log.error("## saveInvoiceApply error", ex);
            throw ex;
        }
    }

    private String getProjectNameAndSubjectName(Order order) {
        StringBuilder projectNameAndSubjectName = new StringBuilder();
        Project project = projectMapper.selectById(order.getBmProjectId());
        if (null != project) {
            String projectName = project.getProjectName();
            projectNameAndSubjectName.append(projectName);
        }
        String subjectNames = studentSubjectMidOrderDetailsMapper.getBmSubjectNamesByOrderId(order.getId());
        if (StringUtils.isNotEmpty(subjectNames)) {
            projectNameAndSubjectName.append("(");
            String[] subjectNamesAttr = subjectNames.split(",");
            if (null != subjectNamesAttr && subjectNamesAttr.length > 0) {
                for (int i = 0; i < subjectNamesAttr.length; i++) {
                    projectNameAndSubjectName.append(subjectNamesAttr[i]);
                    projectNameAndSubjectName.append("/");
                }
                projectNameAndSubjectName.deleteCharAt(projectNameAndSubjectName.length() - 1);
            }
            projectNameAndSubjectName.append(")");
        }

        return projectNameAndSubjectName.toString();
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveInvoice(List<String> invoiceIds) throws Exception {
        List<InvoiceSaveVo> list = invoiceMapper.queryInvoiceByIds(invoiceIds);
        List<InvoiceResult> resultList = invoiceResultMapper.queryResultByIds(invoiceIds);
        try {
            List<Invoice> successInvoice = new ArrayList<Invoice>();
            List<Invoice> failInvoice = new ArrayList<Invoice>();
            List<Invoice> invoiceListAll = new ArrayList<Invoice>();
            List<InvoiceResult> successRes = new ArrayList<>();
            List<InvoiceResult> failRes = new ArrayList<>();
            List<InvoiceResult> resultListAll = new ArrayList<>();
            for (InvoiceSaveVo entityVo : list) {
                InvoiceResult bmInvoiceResult = new InvoiceResult();
                for (int i = 0; i < resultList.size(); i++) {
                    if (resultList.get(i).getBmInvoiceId().equals(entityVo.getId())) {
                        bmInvoiceResult = resultList.get(i);
                        break;
                    }
                }
                // 026 电子发票 004增值税专票，007增值税普票
                if (entityVo.getFplxdm().equals("026")) {
                    // 电子发票
                    entityVo.setCalledType("post_https");
                    entityVo.setOptType("DFXJ1001");
                    String rsData = null;
                    log.info("## invoiceInterface params:{}", FastJsonUtil.getBeanToJson(entityVo));
                    rsData = tpsClient.invoiceInterface(entityVo);
                    log.info("## invoiceInterface result:{}", FastJsonUtil.getBeanToJson(rsData));
                    Map ObjectMap = JSONObject.parseObject(rsData, Map.class);

                    JSONObject json = JSON.parseObject(ObjectMap.get("obj").toString());
                    String qrCodePath = json.getString("qrCodePath");
                    String content = json.getString("invoiceReqSerialNo");
                    String msg = json.getString("msg");
                    String code = json.getString("code");

                    entityVo.setReturnCode(code);
                    entityVo.setReturnMessage(msg);

                    Invoice invoice = new Invoice();
                    BeanUtils.copyProperties(entityVo, invoice);

                    log.info("## saveInvoice() entityVo:{}", FastJsonUtil.getBeanToJson(entityVo));
                    if (entityVo.getReturnCode().equals("0")) {
                        if (!"2".equals(entityVo.getRsCode()) && !"1".equals(entityVo.getRsCode())) {
                            invoice.setBussResult("1");
                            invoice.setRsCode("2");
                            invoice.setRsMsg("已开具");
                            invoice.setDataExchangeId(content);
                            // 1. 发票信息 update
                            successInvoice.add(invoice);
                            // bmStudentInvoiceService.save(entityVo);
                            // 1. 发票结果 update

                            bmInvoiceResult.setBmInvoiceId(entityVo.getId());
                            bmInvoiceResult.setRsCode("2");
                            bmInvoiceResult.setRsMsg("已开具");
                            bmInvoiceResult.setKprq(LocalDateTime.now());
                            bmInvoiceResult.setInnerRsCode("2");
                            bmInvoiceResult.setRsCode("2");
                            if (StringUtils.isNotBlank(qrCodePath)) {
                                bmInvoiceResult.setPdfUrl(new String(Base64.decode(qrCodePath)));
                                bmInvoiceResult.setSpUrl(new String(Base64.decode(qrCodePath)));
                            }
                            bmInvoiceResult.setRsMsg(entityVo.getReturnMessage());
                            successRes.add(bmInvoiceResult);

                            // 修改订单的发票状态
                            QueryWrapper<InvoiceMidOrder> invoiceMidOrderWrapper = new QueryWrapper<InvoiceMidOrder>();
                            invoiceMidOrderWrapper.eq("bm_invoice_id", entityVo.getId());
                            List<InvoiceMidOrder> invoiceMidOrders = iInvoiceMidOrderService.list(invoiceMidOrderWrapper);
                            if (CollUtil.isNotEmpty(invoiceMidOrders)) {
                                for (InvoiceMidOrder invoiceMidOrder : invoiceMidOrders) {
                                    String orderId = invoiceMidOrder.getBmOrderDetailsId();
                                    Order order = iOrderMapper.selectById(orderId);
                                    if (null != order) {
                                        order.setInvoiceStatus(OrderInvioiceStatusEnum.SUCCESS.getStatus());
                                        iOrderMapper.updateById(order);
                                    }
                                }
                            }
                        }
                    } else {
                        invoice.setRsCode("3");
                        invoice.setRsMsg(msg);
                        invoice.setBussResult("3");
                        invoice.setDataExchangeId(content);
                        // 1. 发票信息 update
                        failInvoice.add(invoice);
                        // 2. 发票结果 update
                        bmInvoiceResult.setBmInvoiceId(entityVo.getId());
                        bmInvoiceResult.setRsCode("3");
                        bmInvoiceResult.setRsMsg(entityVo.getReturnMessage());
                        bmInvoiceResult.setKprq(LocalDateTime.now());
                        failRes.add(bmInvoiceResult);

                        // 修改订单的发票状态
                        QueryWrapper<InvoiceMidOrder> invoiceMidOrderWrapper = new QueryWrapper<InvoiceMidOrder>();
                        invoiceMidOrderWrapper.eq("bm_invoice_id", entityVo.getId());
                        InvoiceMidOrder invoiceMidOrder = iInvoiceMidOrderService.getOne(invoiceMidOrderWrapper);
                        if (null != invoiceMidOrder) {
                            String orderId = invoiceMidOrder.getBmOrderDetailsId();
                            Order order = iOrderMapper.selectById(orderId);
                            if (null != order) {
                                order.setInvoiceStatus(OrderInvioiceStatusEnum.FAIL.getStatus());
                                iOrderMapper.updateById(order);
                            }
                        }

                        // 修改发票和订单之间的关系为失效
                        // 更新bm_invoice_mid_order，发票订单信息为失效
                        UpdateWrapper invoiceMidOrderWrapper2 = new UpdateWrapper();
                        invoiceMidOrderWrapper2.eq("bm_invoice_id", entityVo.getId());
                        invoiceMidOrderWrapper2.set("is_del_flag", 1);
                        iInvoiceMidOrderService.update(invoiceMidOrderWrapper2);
                    }
                } else {
                    // 专用纸质
                    // invoice
                    Invoice invoice = new Invoice();
                    entityVo.setBussResult("2");
                    entityVo.setRsCode("2");
                    entityVo.setRsMsg("已开具");
                    BeanUtils.copyProperties(entityVo, invoice);
                    successInvoice.add(invoice);
                    // result
                    bmInvoiceResult.setBmInvoiceId(entityVo.getId());
                    bmInvoiceResult.setRsCode("2");
                    bmInvoiceResult.setRsMsg("已开具");
                    bmInvoiceResult.setKprq(LocalDateTime.now());
                    successRes.add(bmInvoiceResult);
                }

            }
            invoiceListAll.addAll(successInvoice);
            invoiceListAll.addAll(failInvoice);
            resultListAll.addAll(successRes);
            resultListAll.addAll(failRes);
            this.saveOrUpdateBatch(invoiceListAll);
            Boolean result = invoiceResultService.saveOrUpdateBatch(resultListAll);
        } catch (Exception e) {
            log.info("## saveInvoice() error", e);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean callBackForInvoice(String invoiceId, InvoiceNotifyEvent invoiceNotifyEvent) throws Exception {
        try {
            if (StringUtils.isEmpty(invoiceId)) {
                throw new Exception("发票数据不存在");
            }
            Invoice invoice = this.getById(invoiceId);
            if (invoice == null) {
                throw new Exception("发票数据不存在");
            }
            CallBackParam param = new CallBackParam();
            param.setOfficeId(invoice.getOfficeId());
            param.setContent(invoiceNotifyEvent.getContent());
            param.setEvent(invoiceNotifyEvent.getEvent());
            param.setSignature(invoiceNotifyEvent.getSignature());
            String rsData = tpsClient.syncInvoiceResultV2(param);
            log.info("## callBackForInvoice  rsData:{}", rsData);
            // 解析resData数据
            if (StringUtils.isNotEmpty(rsData)) {
                InvoiceNotifyVo invoiceNotifyVo = FastJsonUtil.getJsonToBean(rsData, InvoiceNotifyVo.class);
                String code = invoiceNotifyVo.getCode();
                if ("0000".equals(code)) {
                    QueryWrapper<InvoiceResult> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("bm_invoice_id", invoiceId);
                    InvoiceResult result = invoiceResultService.getOne(queryWrapper);
                    if (null != result) {
                        result.setFpqqlsh(invoiceNotifyVo.getInvoiceReqSerialNo());
                        result.setFpDm(invoiceNotifyVo.getInvoiceCode());
                        result.setFpHm(invoiceNotifyVo.getInvoiceNo());
                        //result.setPdfUrl(invoiceNotifyVo.getDownloadUrl());
                        result.setSpUrl(invoiceNotifyVo.getBuyerAddress());
                        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                        result.setKprq(LocalDateTime.parse(invoiceNotifyVo.getInvoiceDate(), df));
                        result.setInnerRsCode(code);
                        invoice.setRsCode("2");
                        invoice.setRsMsg("开票成功");
                        invoiceResultService.saveOrUpdate(result);
                    }
                    this.saveOrUpdate(invoice);
                    return Boolean.TRUE;
                } else {
                    QueryWrapper<InvoiceResult> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("bm_invoice_id", invoiceId);
                    InvoiceResult result = invoiceResultService.getOne(queryWrapper);
                    if (null != result) {
                        result.setInnerRsCode(code);
                        invoiceResultService.saveOrUpdate(result);
                    }
                    invoice.setRsCode("3");
                    invoice.setRsMsg("开票失败");
                    this.saveOrUpdate(invoice);

                    // 修改订单的发票状态
                    QueryWrapper<InvoiceMidOrder> invoiceMidOrderWrapper2 = new QueryWrapper<InvoiceMidOrder>();
                    invoiceMidOrderWrapper2.eq("bm_invoice_id", invoiceId);
                    InvoiceMidOrder invoiceMidOrder = iInvoiceMidOrderService.getOne(invoiceMidOrderWrapper2);
                    if (null != invoiceMidOrder) {
                        String orderId = invoiceMidOrder.getBmOrderDetailsId();
                        Order order = iOrderMapper.selectById(orderId);
                        if (null != order) {
                            order.setInvoiceStatus(OrderInvioiceStatusEnum.FAIL.getStatus());
                            iOrderMapper.updateById(order);
                        }
                    }
                    return Boolean.TRUE;
                }
            }
            return Boolean.FALSE;
        } catch (Exception ex) {
            log.error("## callBackForInvoice error", ex);
            return Boolean.FALSE;
        }
    }


    @Transactional(rollbackFor = Exception.class)
    public void saveBackForInvoice(String invoiceId) throws Exception {
        try {
            if (StringUtils.isEmpty(invoiceId)) {
                return;
            }
            // 更新发票状态为失效
            UpdateWrapper updateWrapper = new UpdateWrapper();
            updateWrapper.eq("id", invoiceId);
            updateWrapper.set("rs_code", "4");
            updateWrapper.set("rs_msg", "已失效");
            this.update(updateWrapper);

            // 更新结果状态为失效
            UpdateWrapper resultUpdateWrapper = new UpdateWrapper();
            resultUpdateWrapper.eq("bm_invoice_id", invoiceId);
            resultUpdateWrapper.set("rs_code", "4");
            resultUpdateWrapper.set("rs_msg", "已失效");
            // 清空查看地址
            resultUpdateWrapper.set("pdf_url", null);
            invoiceResultService.update(resultUpdateWrapper);

            // 更新bm_invoice_mid_order，发票订单信息为失效
            UpdateWrapper invoiceMidOrderWrapper = new UpdateWrapper();
            invoiceMidOrderWrapper.eq("bm_invoice_id", invoiceId);
            invoiceMidOrderWrapper.set("is_del_flag", 1);
            iInvoiceMidOrderService.update(invoiceMidOrderWrapper);

            // 修改订单的发票状态
            QueryWrapper<InvoiceMidOrder> invoiceMidOrderWrapper2 = new QueryWrapper<InvoiceMidOrder>();
            invoiceMidOrderWrapper2.eq("bm_invoice_id", invoiceId);
            List<InvoiceMidOrder> invoiceMidOrders = iInvoiceMidOrderService.list(invoiceMidOrderWrapper2);
            if (CollUtil.isNotEmpty(invoiceMidOrders)) {
                for (InvoiceMidOrder invoiceMidOrder : invoiceMidOrders) {
                    String orderId = invoiceMidOrder.getBmOrderDetailsId();
                    Order order = iOrderMapper.selectById(orderId);
                    if (null != order) {
                        order.setInvoiceStatus("0");
                        iOrderMapper.updateById(order);
                    }
                }
            }
        } catch (Exception ex) {
            throw ex;
        }
    }

    public List<InvoiceApplyVo> queryOrderDetail(String invoiceId) {
        return invoiceMapper.queryOrderDetail(invoiceId);
    }
    
    
    @Transactional(rollbackFor = Exception.class)
    public Boolean resetInvoiceStatus( User user, String invoiceId) throws Exception {
        // 首先查询发票信息存不存在
        Invoice invoice = invoiceMapper.selectById(invoiceId);
        if(null == invoice) {
            return Boolean.FALSE;
        }
        
        // 获取当前发票的开票状态
        String invoiceStatus = invoice.getRsCode();
        if(StrUtil.isBlankIfStr(invoiceStatus) && !BmInvoiceStatusEnum.FAILINVOICING.getStatus().equals(invoiceStatus)) {
            return Boolean.FALSE;
        }
        
        // 修改发票状态为待确认
        invoice.setRsCode(BmInvoiceStatusEnum.UNINVOICING.getStatus());
        invoice.setRsMsg("待确认");
        invoice.setUpdateBy(user.getId());
        invoice.setUpdateDate(LocalDateTime.now());
        invoiceMapper.updateById(invoice);
        return Boolean.TRUE;
    }
}
